package com.ks.winterwarmimage.utils;

import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Pattern;

public class BasicsUtil {
    private final static String TAG="BasicsUtil";
    /**
     * 获取屏幕分大小
     * @param context 上下文
     * @return
     */
    public static Point getDisplaySize(Context context){
        DisplayMetrics outMetrics  = new DisplayMetrics();
        WindowManager WM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        WM.getDefaultDisplay().getMetrics(outMetrics);
        return new Point(outMetrics.widthPixels,outMetrics.heightPixels);
    }
    /**
     * dp转像素
     * @param dpVal 需要转换的dp值
     * @return 返回像素未单位的值
     */
    public static  int dp2px(Context context, float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, context.getResources().getDisplayMetrics());
    }
    /** sp转换px */
    public static int sp2px(Context context, int spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, context.getResources().getDisplayMetrics());
    }
    public static int px2dp(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
    /**
     * 字符串转字节数组
     * @param hexString 16进制字符串，无任何分隔符，两个一组
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        hexString = hexString.toUpperCase();
        int len = hexString.length();
        byte[] b = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个字节
            b[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
        }
        return b;
    }

    /**
     * 将不包含冒号的Mac或SSID加入冒号
     * @param mac 不含冒号的Mac或SSID字符串
     * @return 包含冒号的Mac或SSID字符串
     */
    public static String addMacColon(String mac) {
        if(mac!=null) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < mac.length(); i++) {
                sb.append(mac.charAt(i));
                if ((i + 1) % 2 == 0 && i != mac.length() - 1) {
                    sb.append(":");
                }
            }
            return sb.toString();
        }
        return null;
    }

    /**
     * 去除Mac的冒号
     * @param mac 包含冒号的Mac字符串
     * @return
     */
    public static String  removeMacColon(String mac){
        if(mac!=null) {
            return mac.replaceAll(":", "");
        }else{
            return "";
        }
    }
    /**
     * Mac或bssid字符串转字节数组
     * @param bssidString
     * @return
     */
    public static byte[] bssidStringToByteArray(String bssidString) {
        // 去除冒号
        String hexBssid = bssidString.replaceAll(":", "");
        // 转换为字节数组
        byte[] bssidBytes = new byte[hexBssid.length() / 2];
        for (int i = 0; i < hexBssid.length(); i += 2) {
            // 每两个字符表示一个字节，将它们转换为十六进制数并存储到字节数组中
            bssidBytes[i / 2] = (byte) ((Character.digit(hexBssid.charAt(i), 16) << 4) + Character.digit(hexBssid.charAt(i + 1), 16));
        }
        return bssidBytes;
    }
    /**
     * 字节数组转16进制字符串
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) {
        StringBuffer sb = new StringBuffer(src.length);
        String sTemp;
        for (int i = 0; i < src.length; i++) {
            sTemp = Integer.toHexString(0xFF & src[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }
    /**
     * 将字节数组转换为16进制字符串
     *
     * @param bytes 字节数组
     * @return 16进制字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex).append(':');
        }
        return hexString.substring(0, hexString.length() - 1); // 去掉最后一个冒号
    }
    public static int bytesToInt(byte[] byteArray,int position, boolean big_endian){
        if (byteArray == null || byteArray.length != 4) {
            throw new IllegalArgumentException("Array must be non-null and exactly 4 bytes long.");
        }
        ByteBuffer buffer;
        if(big_endian){
            buffer = ByteBuffer.wrap(byteArray, position,4);
        }else{
            buffer = ByteBuffer.wrap(byteArray, position,4);
            buffer.order(ByteOrder.LITTLE_ENDIAN); // 设置为小端序
        }
        return buffer.getInt();
    }
    /**
     * 设置颜色透明度
     * @param color 需要设置的颜色
     * @param alpha 透明度
     * @return 返回新的颜色
     */
    public static int setTransparency(int color, int alpha) {
        alpha = (alpha << 24);
        return (color & 0x00ffffff) | alpha;
    }
    /**
     * 设置View长按事件,调用该方法实现长按后请不要再使用原生长按事件。
     * @param longClickView     被长按的视图(任意控件)
     * @param delayMillis       长按时间,毫秒
     * @param longClickListener 长按回调的返回事件
     */
    public static void setLongClick(final View longClickView, final long delayMillis, final View.OnLongClickListener longClickListener) {
        longClickView.setOnLongClickListener(new View.OnLongClickListener() {
            private long newDelayMillis=delayMillis-500;
            @Override
            public boolean onLongClick(View v) {
                new Timer().schedule(new TimerTask() {
                    @Override
                    public void run() {
                        if (longClickListener != null) {// 回调给用户,用户可能传null,需要判断null
                            longClickListener.onLongClick(longClickView);
                        }
                    }
                },newDelayMillis);//延时1s执行
                return true;
            }
        });
    }

    /**
     * 判断软键盘是否开启
     * @param context
     * @return
     */
    public static boolean isSoftShowing(Context context) {
        View view= ((Activity)context).getWindow().getDecorView();
        if(view!=null) {
            //获取当屏幕内容的高度
            int screenHeight = view.getHeight();
            //获取View可见区域的bottom
            Rect rect = new Rect();
            //DecorView即为activity的顶级view
            view.getWindowVisibleDisplayFrame(rect);
            //考虑到虚拟导航栏的情况（虚拟导航栏情况下：screenHeight = rect.bottom + 虚拟导航栏高度）
            //选取screenHeight*2/3进行判断
            return screenHeight * 2 / 3 > rect.bottom;
        }else{
            return false;
        }
    }

    /**
     * 两个字节数组拼接
     * @param bt1 待拼接的字节数组1
     * @param bt2 待拼接的字节数组2
     * @return 拼接后的数组。bt1+bt2
     */
    public static byte[] byteMerger(byte[] bt1, byte[] bt2){
        byte[] bt3 = new byte[bt1.length+bt2.length];
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);
        System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
        return bt3;
    }

    /**
     * 字节数组裁剪。不改变原数组
     * @param b 原数组
     * @param offset 偏差值（索引从0开始计算）
     * @return 截取后的数组
     */
    public static byte[] subByte(byte[] b,int offset){
        int length=b.length-offset;
        return subByte(b,offset,length);
    }
    /**
     * 截取byte数组   不改变原数组
     * @param b 原数组
     * @param offset 偏差值（索引从0开始计算）
     * @param length 长度
     * @return 截取后的数组
     */
    public static byte[] subByte(byte[] b,int offset,int length){
        byte[] b1 = new byte[length];
        System.arraycopy(b, offset, b1, 0, length);
        return b1;
    }

    /**
     * 截取byte数组   不改变原数组
     * @param b 原数组
     * @param beginIndex 开始索引
     * @param endIndex 结束索引
     * @return
     */
    public static byte[] subByteE(byte[] b,int beginIndex,int endIndex){
        int length=endIndex-beginIndex-1;
        return subByte(b,beginIndex,length);
    }
    /**
     * 返回第一个参数的值，并将其提升为第二个参数的幂。特殊情况：
     *
     *<ul><li>如果第二个参数为正零或负零，则结果为1.0。
     *<li>如果第二个参数为1.0，则结果与第一个参数相同。
     *<li>如果第一个参数为1.0，则结果为1.0。
     *<li>如果第二个参数为NaN，则结果为NaN，除非第一个参数为1.0。
     *<li>如果第一个参数为NaN，第二个参数为非零，则结果为NaN。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数的绝对值大于1，第二个参数为正无穷大，或
     *<li>第一个参数的绝对值小于1，第二个参数为负无穷大，
     *</ul>
     *那么结果就是正无穷大。
     *<li>如果
     *<ul>
     *<li>第一个参数的绝对值大于1，第二个参数为负无穷大，或
     *<li>第一个参数的绝对值小于1，第二个参数为正无穷大，
     *</ul>
     *那么结果是正零。
     *
     *<li>如果第一个参数的绝对值等于1，第二个参数为无穷大，则结果为1.0。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数为正零，第二个参数大于零，或
     *<li>第一个参数为正无穷大，第二个参数小于零，
     *</ul>
     *那么结果是正零。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数为正零，第二个参数小于零，或
     *<li>第一个参数为正无穷大，第二个参数大于零，
     *</ul>
     *那么结果就是正无穷大。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数为负零，第二个参数大于零但不是有限的奇数整数，或
     *<li>第一个参数为负无穷大，第二个参数小于零但不是有限的奇整数，
     *</ul>
     *那么结果是正零。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数为负零，第二个参数为正有限奇数整数，或
     *<li>第一个参数为负无穷大，第二个参数为负有限奇整数，
     *</ul>
     *那么结果是负零。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数为负零，第二个参数为负零
     *小于零但不是有限奇数整数，或
     *<li>第一个参数是负无穷大，第二个参数是负无穷大
     *参数大于零但不是有限的奇数整数，
     *</ul>
     *那么结果就是正无穷大。
     *
     *<li>如果
     *<ul>
     *<li>第一个参数为负零，第二个参数为负有限奇数整数，或
     *<li>第一个参数为负无穷大，第二个参数为正有限奇整数，
     *</ul>
     *那么结果就是负无穷大。
     *
     *<li>如果第一个参数是有限的且小于零
     *<ul>
     *<li>如果第二个参数是有限偶数整数，则结果等于将第一个参数的绝对值提升到第二个参数的幂的结果
     *
     *<li>如果第二个参数是有限的奇数整数，则结果等于将第一个参数的绝对值提升到第二个参数的幂的结果的负数
     *
     *<li>如果第二个参数是有限的而不是整数，则结果为NaN。
     *</ul>
     *
     *<li>如果两个参数都是整数，那么结果正好等于将第一个参数提升为第二个参数的幂的数学结果，如果该结果实际上可以精确地表示为{@code double}值。</ul>
     *
     *<p>（在前面的描述中，浮点值被认为是整数，当且仅当它是有限的，并且是方法 {@link Math#ceil ceil}的不动点，或者，等效地，是方法 {@link Math#floor  floor}的不动点。值是单参数方法的固定点，当且仅当将该方法应用于该值的结果等于该值时。）
     *
     *<p>计算结果必须在精确结果的1 ulp范围内。
     *结果必须是半单调的。
     *
     * @param a 基值
     * @param b 指数
     * @return
     */
    public static int pow(int a,int b){
        Math.pow(a,b);
        int tempPow=1;
        for(int i=0;i<b;i++)
            tempPow*=a;
        return tempPow;
    }

    /**
     * 指定的浮点类型数字是整数？
     * @param value 需要判断的浮点数据
     * @return
     */
    public static boolean isIntegerForDouble(double value) {
        double eps = 1e-10;  // 精度范围
        return value-Math.floor(value) < eps;
    }

    /**
     * 将一个数值从一个范围映射到另一个指定的范围。
     * @param value 要映射的值
     * @param fromLow 值当前范围的下限
     * @param fromHigh 值的当前范围的上限
     * @param toLow 值的目标范围的下限
     * @param toHigh 值的目标范围的上限
     * @return 被映射的新的数值
     */
    public static int map(int value,int fromLow,int fromHigh,int toLow,int toHigh){
        return (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
    }

    /**
     * 判断字符串是否为合法的数字类型数据
     * @param number
     * @return
     */
    public static boolean isNumber(String number){
        /**合法数字的要求：
         1、小数点可以在字符串的任意位置均为浮点数；
         2、+或-号只能出现在字符串的第一位；
         3、数字尾部可以出现“l,f,d,L,F,D”
         4、如果数字为整数，尾部只能出现"l或L"字符
         */
        boolean mReturn=number.matches("-?[0-9]+.？[0-9]*");
        if(!mReturn) {
            //对前两个字符为"-+"或"+-"的进行转换
            if (number.indexOf("+-") == 0 || number.indexOf("-+") == 0) {
                number = "-" + number.substring(2);
            }
            //处理多个小数点的情况
            if (number.contains(".")) {
                String temp = number.replace(".", "");
                int cnt = number.length() - temp.length();
                if (cnt > 1) {
                    return false;
                } else {
                    int pos = number.length() - 1;
                    //判断最后一位是否为数字类型符
                    if (number.lastIndexOf("f") == pos || number.lastIndexOf("F") == pos ||
                            number.lastIndexOf("d") == pos || number.lastIndexOf("D") == pos) {
                        number = number.substring(0, pos);   //去掉尾部强制数字类型符号
                    }
                }
            } else {
                int pos = number.length() - 1;
                //判断最后一位是否为数字类型符
                if (number.lastIndexOf("l") == pos || number.lastIndexOf("L") == pos) {
                    number = number.substring(0, pos);   //去掉尾部强制数字类型符号
                }
            }
            //数字校验（可以包含小数，可以是1，0，-1，1.1，-1.1；不能是+1.1，+1）
            mReturn = Pattern.compile("^-?\\d+(\\.\\d+)?$").matcher(number).find();
            if (!mReturn)
                //处理小数点或"+"在第一位的情况。不能处理"+."或"-."
                mReturn = Pattern.compile("^.?\\d+(\\.\\d+)?$").matcher(number).find();
            if (!mReturn)
                //尾部带小数点的浮点数
                mReturn = Pattern.compile("^-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0)$").matcher(number).find();
            if (!mReturn)
                mReturn = Pattern.compile("^[-\\+]?[.\\d]*$").matcher(number).find();
        }
        return mReturn;
    }
}
